<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>限流算法：令牌桶与漏桶</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
        }
        .serif-font {
            font-family: 'Noto Serif SC', serif;
        }
        .gradient-text {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        .card-hover {
            transition: all 0.3s ease;
        }
        .card-hover:hover {
            transform: translateY(-4px);
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
        }
        .code-block {
            background: linear-gradient(135deg, #1e1e2e 0%, #2d2d44 100%);
            border-radius: 12px;
            overflow: hidden;
        }
        .highlight-line {
            background: rgba(255, 255, 255, 0.05);
            border-left: 3px solid #667eea;
            margin-left: -1rem;
            padding-left: calc(1rem - 3px);
        }
        @keyframes float {
            0%, 100% { transform: translateY(0px); }
            50% { transform: translateY(-10px); }
        }
        .float-animation {
            animation: float 3s ease-in-out infinite;
        }
        .drop-cap {
            float: left;
            font-size: 4rem;
            line-height: 3rem;
            padding-right: 0.5rem;
            margin-top: 0.5rem;
            font-weight: 700;
            color: #667eea;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="relative overflow-hidden bg-gradient-to-br from-purple-900 via-purple-800 to-indigo-900 text-white">
        <div class="absolute inset-0 bg-black opacity-20"></div>
        <div class="relative container mx-auto px-6 py-24">
            <div class="max-w-4xl mx-auto text-center">
                <h1 class="text-5xl md:text-7xl font-bold mb-6 serif-font">
                    <span class="gradient-text">限流算法</span>
                </h1>
                <p class="text-2xl md:text-3xl mb-8 font-light">令牌桶与漏桶的艺术</p>
                <div class="flex justify-center space-x-8 text-lg">
                    <div class="flex items-center">
                        <i class="fas fa-tachometer-alt mr-2"></i>
                        <span>高并发控制</span>
                    </div>
                    <div class="flex items-center">
                        <i class="fas fa-shield-alt mr-2"></i>
                        <span>系统保护</span>
                    </div>
                    <div class="flex items-center">
                        <i class="fas fa-balance-scale mr-2"></i>
                        <span>流量均衡</span>
                    </div>
                </div>
            </div>
        </div>
        <div class="absolute bottom-0 left-0 right-0">
            <svg viewBox="0 0 1440 120" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M0 120L60 110C120 100 240 80 360 70C480 60 600 60 720 65C840 70 960 80 1080 85C1200 90 1320 90 1380 90L1440 90V120H1380C1320 120 1200 120 1080 120C960 120 840 120 720 120C600 120 480 120 360 120C240 120 120 120 60 120H0V120Z" fill="#F9FAFB"/>
            </svg>
        </div>
    </section>

    <!-- Introduction Section -->
    <section class="container mx-auto px-6 py-16">
        <div class="max-w-4xl mx-auto">
            <div class="bg-white rounded-2xl shadow-xl p-8 md:p-12 card-hover">
                <p class="text-lg leading-relaxed text-gray-700">
                    <span class="drop-cap serif-font">在</span>高并发的数字世界中，系统如同繁忙的高速公路，需要精确的流量控制来保证稳定运行。限流算法就是这样的交通管制系统，它们优雅地平衡着用户需求与系统承载能力之间的关系。今天，让我们深入探索两种经典的限流算法：令牌桶和漏桶，理解它们如何守护着系统的稳定性。
                </p>
            </div>
        </div>
    </section>

    <!-- Algorithm Comparison -->
    <section class="container mx-auto px-6 py-16">
        <div class="max-w-6xl mx-auto">
            <h2 class="text-4xl font-bold text-center mb-12 serif-font">算法对比</h2>
            <div class="grid md:grid-cols-2 gap-8">
                <!-- Token Bucket Card -->
                <div class="bg-gradient-to-br from-purple-50 to-indigo-50 rounded-2xl p-8 card-hover border border-purple-200">
                    <div class="flex items-center mb-6">
                        <div class="w-16 h-16 bg-purple-600 rounded-full flex items-center justify-center mr-4 float-animation">
                            <i class="fas fa-coins text-white text-2xl"></i>
                        </div>
                        <h3 class="text-2xl font-bold text-purple-900">令牌桶算法</h3>
                    </div>
                    <ul class="space-y-4 text-gray-700">
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-purple-600 mt-1 mr-3"></i>
                            <span>以固定速率生成令牌，存储在容量有限的桶中</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-purple-600 mt-1 mr-3"></i>
                            <span>请求需要消耗令牌才能被处理</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-purple-600 mt-1 mr-3"></i>
                            <span>允许突发流量，灵活性高</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-purple-600 mt-1 mr-3"></i>
                            <span>时间复杂度 O(1)，空间复杂度 O(1)</span>
                        </li>
                    </ul>
                </div>

                <!-- Leaky Bucket Card -->
                <div class="bg-gradient-to-br from-blue-50 to-cyan-50 rounded-2xl p-8 card-hover border border-blue-200">
                    <div class="flex items-center mb-6">
                        <div class="w-16 h-16 bg-blue-600 rounded-full flex items-center justify-center mr-4 float-animation">
                            <i class="fas fa-faucet text-white text-2xl"></i>
                        </div>
                        <h3 class="text-2xl font-bold text-blue-900">漏桶算法</h3>
                    </div>
                    <ul class="space-y-4 text-gray-700">
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-blue-600 mt-1 mr-3"></i>
                            <span>请求以固定速率流出处理</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-blue-600 mt-1 mr-3"></i>
                            <span>桶满时新请求被丢弃</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-blue-600 mt-1 mr-3"></i>
                            <span>输出速率恒定，平滑流量</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-blue-600 mt-1 mr-3"></i>
                            <span>适合需要稳定处理速率的场景</span>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </section>

    <!-- Visual Diagram -->
    <section class="bg-gray-100 py-16">
        <div class="container mx-auto px-6">
            <div class="max-w-6xl mx-auto">
                <h2 class="text-4xl font-bold text-center mb-12 serif-font">算法原理可视化</h2>
                <div class="bg-white rounded-2xl shadow-xl p-8">
                    <div class="mermaid">
                        graph TB
                            subgraph 令牌桶
                                A[令牌生成器] -->|固定速率| B[令牌桶]
                                C[请求] -->|消耗令牌| B
                                B -->|有令牌| D[处理请求]
                                B -->|无令牌| E[拒绝请求]
                            end
                            
                            subgraph 漏桶
                                F[请求] --> G[漏桶]
                                G -->|固定速率| H[处理请求]
                                G -->|桶满| I[丢弃请求]
                            end
                            
                            style A fill:#9333ea,stroke:#7c3aed,color:#fff
                            style B fill:#a855f7,stroke:#9333ea,color:#fff
                            style G fill:#3b82f6,stroke:#2563eb,color:#fff
                            style H fill:#60a5fa,stroke:#3b82f6,color:#fff
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Code Implementation -->
    <section class="container mx-auto px-6 py-16">
        <div class="max-w-6xl mx-auto">
            <h2 class="text-4xl font-bold text-center mb-12 serif-font">代码实现</h2>
            
            <!-- Token Bucket Implementation -->
            <div class="mb-12">
                <h3 class="text-2xl font-bold mb-6 flex items-center">
                    <i class="fas fa-code text-purple-600 mr-3"></i>
                    令牌桶实现
                </h3>
                <div class="code-block">
                    <div class="bg-gray-800 px-6 py-3 flex items-center justify-between">
                        <span class="text-gray-400 text-sm">TokenBucket.java</span>
                        <i class="fas fa-copy text-gray-400 cursor-pointer hover:text-white"></i>
                    </div>
                    <pre class="text-gray-300 p-6 overflow-x-auto"><code>public class TokenBucket {
    private final double capacity;    // 桶的容量
    private double tokens;           // 当前令牌数量
    private final double rate;       // 令牌生成速率（每秒）
    private long lastRefillTime;     // 上次添加令牌的时间
    
    public TokenBucket(double capacity, double rate) {
        this.capacity = capacity;
        this.tokens = capacity;      // 初始时桶是满的
        this.rate = rate;
        this.lastRefillTime = System.currentTimeMillis();
    }
    
    public synchronized boolean allowRequest() {
        long now = System.currentTimeMillis();
        
        <span class="highlight-line">// 计算并添加新令牌
        double newTokens = (now - lastRefillTime) / 1000.0 * rate;
        tokens = Math.min(capacity, tokens + newTokens);</span>
        
        lastRefillTime = now;
        
        <span class="highlight-line">// 尝试消耗令牌
        if (tokens >= 1) {
            tokens -= 1;
            return true;
        }</span>
        
        return false;
    }
}</code></pre>
                </div>
            </div>

            <!-- Leaky Bucket Implementation -->
            <div>
                <h3 class="text-2xl font-bold mb-6 flex items-center">
                    <i class="fas fa-code text-blue-600 mr-3"></i>
                    漏桶实现
                </h3>
                <div class="code-block">
                    <div class="bg-gray-800 px-6 py-3 flex items-center justify-between">
                        <span class="text-gray-400 text-sm">LeakyBucket.java</span>
                        <i class="fas fa-copy text-gray-400 cursor-pointer hover:text-white"></i>
                    </div>
                    <pre class="text-gray-300 p-6 overflow-x-auto"><code>public class LeakyBucket {
    private final int capacity;      // 桶的容量
    private int water;              // 当前水量（请求数）
    private final double rate;      // 流出速率（每秒）
    private long lastLeakTime;      // 上次漏水时间
    
    public LeakyBucket(int capacity, double rate) {
        this.capacity = capacity;
        this.water = 0;
        this.rate = rate;
        this.lastLeakTime = System.currentTimeMillis();
    }